﻿// (c) Copyright 2013 Mike Riedel.
// This source is subject to the Microsoft Public License (Ms-PL).
// All other rights reserved.

using FreshMeat.ErrorHandlingBlock;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ErrorHandlingBlock.Tests
{
   [TestClass]
   public class ErrorPolicyTest
   {
      [TestMethod]
      public void DefaultInstance()
      {
         var policy = new ErrorPolicy();
         var error = new FakeException1();

         Assert.IsTrue(policy.IsApplicable(error), "Default policy should always be applicable.");

         var result = policy.Apply(error, 1);
         Assert.AreSame(error, result.Diagnosis, "Diagnosis should be same instance as original error.");
         Assert.IsFalse(result.ShouldRetry, "Default retry should always be false.");
      }

      [TestMethod]
      public void UsesDetector()
      {
         var detector = new FakeDetector { RelevantType = typeof(FakeException1), DesiredDiagnoseResult = new FakeException2() };
         var policy = new ErrorPolicy(detector, new NoRetryPlan());
         var error1 = new FakeException1();
         var error2 = new FakeException2();

         Assert.IsTrue(policy.IsApplicable(error1), "Should be applicable for expected exception type.");
         Assert.IsFalse(policy.IsApplicable(error2), "Should not be applicable for different exception type.");

         var result = policy.Apply(error1, 1);
         Assert.IsInstanceOfType(result.Diagnosis, typeof(FakeException2), "Should have diagnosed as different type.");
      }

      [TestMethod]
      public void UsesRetryPlan()
      {
         var policy = new ErrorPolicy(new DefaultErrorDetector(), new FakeRetryPlan(3));
         var error = new FakeException1();

         Assert.IsTrue(policy.IsApplicable(error), "Should always be applicable with default detector.");

         var result1 = policy.Apply(error, 1);
         Assert.IsTrue(result1.ShouldRetry, "Should retry on attempt 1.");

         // ReSharper disable HeuristicUnreachableCode
         // ReSharper is wrong -- this code is all EMPERICALLY reachable.

         var result2 = policy.Apply(error, 2);
         Assert.IsTrue(result2.ShouldRetry, "Should retry on attempt 2.");

         var result3 = policy.Apply(error, 3);
         Assert.IsFalse(result3.ShouldRetry, "Should not retry on attempt 3.");

         // ReSharper restore HeuristicUnreachableCode
      }
   }
}
